<template>
  <view class="video" :style="[getStyle]" @click.stop>
    <view v-if="showPoster && !autoplay && isAppPlus" class="video__poster" @click.stop="handleStart">
      <image :src="poster || innerPoster" class="video__poster__img" mode="aspectFill"></image>
      <view class="video__poster__btn">
        <m-icon name="fillarrow-right" size="44" color="#fff" />
      </view>
    </view>
    <video
      v-else
      id="video"
      ref="video"
      :src="src"
      :autoplay="autoplay || Autoplay"
      :loop="loop"
      :muted="muted"
      :controls="controls"
      :enable-progress-gesture="enableProgressGesture"
      :enable-play-gesture="enablePlayGesture"
      :poster="poster"
      x5-video-player-type="h5"
      x-webkit-airplay="allow"
      object-fit="contain"
      webkit-playsinline="true"
      :style="customStyle"
      :initial-time="initialTime"
      @play="handlePlay"
      @pause="handlePause"
      @ended="handleEnded"
      @timeupdate="timeupdate"
    />
  </view>
</template>

<script lang="ts">
import { isH5, isAppPlus } from '@/utils/platform'
import { defineComponent, onMounted, reactive, toRefs, computed } from '@vue/composition-api'
import getCurrentComponent from '@/utils/get-current-component'
import { usePageScroll } from '@/hooks'
import boundingClientRect from '@/utils/bounding-client-rect'
import sleep from '@/utils/sleep'
import addUnit from '@/utils/add-unit'
import { getVideoPoster } from '@/utils'

export default defineComponent({
  props: {
    src: {
      type: String,
      default: '',
    },
    autoplay: { type: Boolean, default: false },
    poster: { type: String, default: '' },
    loop: { type: Boolean, default: false },
    controls: { type: Boolean, default: true },
    muted: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    customClick: { type: Boolean, default: false },
    enableProgressGesture: { type: Boolean, default: true },
    enablePlayGesture: { type: Boolean, default: false },
    customStyle: { type: Object, default: () => ({}) },
    initialTime: { type: Number, default: 0 },
    objectFit: { type: String, default: 'contain' },
    showMuteBtn: { type: Boolean, default: false },
    height: { type: [Number, String], default: 422 },
  },
  emits: ['play', 'pause', 'playend', 'timeupdate'],
  setup(props, { emit }) {
    const vm: any = getCurrentComponent()
    let getVideoHeight = 0
    const handlePlay = async () => {
      if (getVideoHeight === 0) {
        const rect: any = await boundingClientRect('.video', vm)
        getVideoHeight = rect.height
        state.minTop = state.scrollTop - rect.top
        state.maxTop = state.minTop + state.windowHeight - getVideoHeight
      }
      emit('play')
    }
    const handlePause = () => {
      if (!props.loop) {
        state.showPoster = true
      }

      emit('pause')
    }
    const handleEnded = () => {
      state.showPoster = true
      emit('playend')
    }

    const handleStart = () => {
      if (props.customClick) {
        emit('play')
      } else {
        state.showPoster = false
        state.Autoplay = true
        handlePlay()
      }
    }
    const timeupdate = (e) => {
      emit('timeupdate', e)
    }
    const systemInfo: any = uni.getSystemInfoSync()
    const state = reactive({
      windowHeight: systemInfo.windowHeight,
      scrollTop: 0,
      minTop: 0,
      maxTop: 0,
      showPoster: true,
      Autoplay: false,
      innerPoster: '',
    })

    const getStyle = computed(() => {
      return {
        height: addUnit(props.height),
      }
    })

    onMounted(async () => {
      await sleep(30)
      if (isAppPlus && !props.poster) {
        state.innerPoster = (await getVideoPoster(props.src)) as string
      }
      if (isH5 && props.autoplay) {
        try {
          vm.$refs.video.muted = true
          vm.$refs.video.play()
        } catch (ex) {}
      }
    })

    usePageScroll(async ({ scrollTop }) => {
      state.scrollTop = scrollTop

      // 判断元素是否已经出了可视区
      if (scrollTop < state.minTop || scrollTop > state.maxTop) {
        const e = uni.createVideoContext('video', vm)
        e.pause()
      }
    })

    return {
      ...toRefs(state),
      handlePlay,
      handlePause,
      handleEnded,
      handleStart,
      isAppPlus,
      timeupdate,
      getStyle,
    }
  },
})
</script>
<style lang="scss" scoped>
.video {
  width: 100% !important;
  position: relative;
  background: #333;
  height: 100%;
  &__poster {
    height: 100%;
    width: 100%;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    &__img {
      width: 100%;
      height: 100%;
      margin: auto;
    }
    &__btn {
      border: 6rpx solid #fff;
      padding: 20rpx;
      border-radius: 50px;
      z-index: 9;
      position: absolute;
      margin: auto;
      display: inline;
    }
  }

  ::v-deep video {
    width: 100%;
    height: 100%;
  }
}
</style>
